<template>
  <view class="xl-printer-container">
    <view class="printer-status">
      <view class="status-badge" :class="{ 'status-connected': isConnected, 'status-disconnected': !isConnected }">
        <text>{{ isConnected ? '已连接' : '未连接' }}</text>
      </view>
      <text class="printer-name">{{ connectedPrinter ? connectedPrinter.name || connectedPrinter.deviceId : '未连接打印机' }}</text>
    </view>
    
    <view class="printer-controls">
      <button class="control-btn" :disabled="isConnecting || isConnected" @click="startSearch">搜索打印机</button>
      <button class="control-btn" :disabled="!isConnected" @click="disconnect">断开连接</button>
      <button class="control-btn" :disabled="!isConnected" @click="testPrint">测试打印</button>
    </view>
    
    <!-- 打印机列表 -->
    <view class="printer-list" v-if="isSearching">
      <view class="list-header">
        <text>可用打印机</text>
        <text class="refresh-btn" @click="startSearch">刷新</text>
      </view>
      
      <scroll-view class="device-scroll" scroll-y="true">
        <view v-if="printers.length === 0" class="no-device">
          <text>正在搜索打印机...</text>
        </view>
        <view v-else>
          <view 
            v-for="(printer, index) in printers" 
            :key="printer.deviceId" 
            class="device-item"
            :class="{ 'device-connected': printer.connected }"
            @click="connectToPrinter(printer)"
          >
            <view class="device-icon">
              <text class="icon-printer">🖨️</text>
            </view>
            <view class="device-info">
              <text class="device-name">{{ printer.name || '未知设备' }}</text>
              <text class="device-id">ID: {{ printer.deviceId }}</text>
              <text class="device-rssi">信号强度: {{ printer.RSSI || 'N/A' }}</text>
            </view>
            <view class="device-action">
              <text v-if="printer.connected">已连接</text>
              <text v-else-if="connectingDeviceId === printer.deviceId">连接中...</text>
              <text v-else class="connect-text">点击连接</text>
            </view>
          </view>
        </view>
      </scroll-view>
    </view>
    
    <!-- 打印参数设置 -->
    <view class="print-settings" v-if="isConnected">
      <view class="settings-title">打印设置</view>
      <view class="setting-item">
        <text class="setting-label">浓度</text>
        <slider :value="printDensity" min="0" max="15" show-value @change="onDensityChange" />
      </view>
      <view class="setting-item">
        <text class="setting-label">字体大小</text>
        <radio-group class="font-size-group" @change="onFontSizeChange">
          <label class="font-size-item" v-for="size in fontSizes" :key="size.value">
            <radio :value="size.value" :checked="printFontSize === size.value" />
            <text>{{ size.label }}</text>
          </label>
        </radio-group>
      </view>
    </view>
    
    <!-- 打印内容输入 -->
    <view class="print-content" v-if="isConnected">
      <view class="content-title">打印内容</view>
      <textarea 
        class="content-textarea" 
        v-model="printContent" 
        placeholder="请输入要打印的文本"
        :disabled="isPrinting"
      />
      <button 
        class="print-btn" 
        :disabled="!printContent || isPrinting" 
        @click="printText"
      >{{ isPrinting ? '打印中...' : '打印' }}</button>
    </view>
    
    <!-- 打印状态 -->
    <view class="print-status" v-if="printStatus">
      <text :class="'status-' + printStatus.type">{{ printStatus.message }}</text>
    </view>
  </view>
</template>

<script setup>
import { ref, reactive, onMounted, onBeforeUnmount, defineComponent, defineExpose } from 'vue';

// 状态变量
const isConnected = ref(false);
const isConnecting = ref(false);
const isSearching = ref(false);
const isPrinting = ref(false);
const connectedPrinter = ref(null);
const printers = ref([]);
const connectingDeviceId = ref('');
const printStatus = ref(null);

// 打印设置
const printDensity = ref(10);
const printFontSize = ref('0');
const printContent = ref('');
const fontSizes = [
  { value: '0', label: '标准' },
  { value: '1', label: '大号' },
  { value: '2', label: '小号' }
];

// 蓝牙服务相关变量
const deviceService = ref(null);
const writeCharacteristic = ref(null);
const notifyCharacteristic = ref(null);

// ESC/POS 命令集 - 用于控制打印机
const ESC = '\x1B';
const GS = '\x1D';
const COMMANDS = {
  INIT: ESC + '@',                     // 初始化打印机
  LINE_FEED: '\n',                     // 换行
  CUT: GS + 'V' + '\x01',              // 切纸
  CENTER: ESC + 'a' + '\x01',          // 居中对齐
  LEFT: ESC + 'a' + '\x00',            // 左对齐
  RIGHT: ESC + 'a' + '\x02',           // 右对齐
  BOLD_ON: ESC + 'E' + '\x01',         // 加粗开
  BOLD_OFF: ESC + 'E' + '\x00',        // 加粗关
  TEXT_SIZE: (n) => ESC + '!' + String.fromCharCode(n), // 设置字体大小
  DENSITY: (n) => GS + '\x42' + String.fromCharCode(n), // 设置打印浓度
};

// 显示状态信息
const showStatus = (type, message) => {
  printStatus.value = { type, message };
  setTimeout(() => {
    printStatus.value = null;
  }, 3000);
};

// 初始化蓝牙
const initBluetooth = async () => {
  try {
    // 检查蓝牙是否可用
    const res = await uni.openBluetoothAdapter();
    if (!res.errMsg.includes('ok')) {
      showStatus('error', '蓝牙初始化失败');
      return false;
    }

    // 监听蓝牙状态变化
    uni.onBluetoothAdapterStateChange((res) => {
      if (!res.available) {
        showStatus('error', '蓝牙已关闭');
        isConnected.value = false;
        connectedPrinter.value = null;
      }
    });

    // 监听蓝牙连接状态变化
    uni.onBLEConnectionStateChange((res) => {
      if (!res.connected) {
        // 设备断开连接
        const deviceIndex = printers.value.findIndex(p => p.deviceId === res.deviceId);
        if (deviceIndex >= 0) {
          printers.value[deviceIndex].connected = false;
        }
        if (connectedPrinter.value && connectedPrinter.value.deviceId === res.deviceId) {
          isConnected.value = false;
          connectedPrinter.value = null;
          showStatus('warning', '打印机连接已断开');
        }
      }
    });

    return true;
  } catch (error) {
    console.error('初始化蓝牙失败:', error);
    showStatus('error', '初始化蓝牙失败');
    return false;
  }
};

// 开始搜索打印机
const startSearch = async () => {
  try {
    isSearching.value = true;
    printers.value = [];
    
    // 开始搜索设备
    uni.showLoading({ title: '搜索中...' });
    await uni.startBluetoothDevicesDiscovery({
      allowDuplicatesKey: false,
      powerLevel: 'high',
    });
    
    // 监听设备发现事件
    uni.onBluetoothDeviceFound((res) => {
      if (!res.devices || res.devices.length === 0) return;
      
      res.devices.forEach(device => {
        // 检查是否是打印机 - 根据设备名称关键字、服务等过滤
        if (isPrinterDevice(device)) {
          // 检查设备是否已在列表中
          const existingIndex = printers.value.findIndex(p => p.deviceId === device.deviceId);
          
          if (existingIndex >= 0) {
            // 更新现有设备信息
            printers.value[existingIndex] = {
              ...printers.value[existingIndex],
              ...device,
              lastSeen: Date.now()
            };
          } else {
            // 添加新设备
            printers.value.push({
              ...device,
              connected: false,
              lastSeen: Date.now()
            });
          }
          
          // 按信号强度排序
          printers.value.sort((a, b) => (b.RSSI || -100) - (a.RSSI || -100));
        }
      });
    });

    // 设置搜索超时
    setTimeout(() => {
      stopSearch();
    }, 10000);
  } catch (error) {
    console.error('搜索打印机失败:', error);
    showStatus('error', '搜索打印机失败');
    isSearching.value = false;
    uni.hideLoading(); // 确保在错误时也关闭加载状态
  }
};

// 停止搜索
const stopSearch = async () => {
  try {
    await uni.stopBluetoothDevicesDiscovery();
    isSearching.value = false;
    uni.hideLoading();
  } catch (error) {
    console.error('停止搜索失败:', error);
    isSearching.value = false;
    uni.hideLoading(); // 确保在错误时也关闭加载状态
  }
};

// 连接打印机
const connectToPrinter = async (printer) => {
  try {
    isConnecting.value = true;
    connectingDeviceId.value = printer.deviceId;
    
    // 连接设备
    await uni.createBLEConnection({
      deviceId: printer.deviceId
    });
    
    // 获取设备服务
    const servicesRes = await uni.getBLEDeviceServices({
      deviceId: printer.deviceId
    });
    
    // 查找打印机服务
    const printerService = servicesRes.services.find(service => 
      service.uuid.toLowerCase().includes('ff00') || 
      service.uuid.toLowerCase().includes('ae30')
    );
    
    if (!printerService) {
      throw new Error('未找到打印机服务');
    }
    
    deviceService.value = printerService;
    
    // 获取特征值
    const characteristicsRes = await uni.getBLEDeviceCharacteristics({
      deviceId: printer.deviceId,
      serviceId: printerService.uuid
    });
    
    // 查找写入特征值
    const writeChar = characteristicsRes.characteristics.find(char => 
      char.properties.write || char.properties.writeNoResponse
    );
    
    if (!writeChar) {
      throw new Error('未找到写入特征值');
    }
    
    writeCharacteristic.value = writeChar;
    
    // 更新状态
    isConnected.value = true;
    connectedPrinter.value = printer;
    printer.connected = true;
    
    showStatus('success', '打印机连接成功');
  } catch (error) {
    console.error('连接打印机失败:', error);
    showStatus('error', '连接打印机失败');
  } finally {
    isConnecting.value = false;
    connectingDeviceId.value = '';
  }
};

// 断开连接
const disconnect = async () => {
  try {
    if (!connectedPrinter.value) return;
    
    await uni.closeBLEConnection({
      deviceId: connectedPrinter.value.deviceId
    });
    
    isConnected.value = false;
    connectedPrinter.value = null;
    deviceService.value = null;
    writeCharacteristic.value = null;
    notifyCharacteristic.value = null;
    
    showStatus('success', '打印机已断开连接');
  } catch (error) {
    console.error('断开连接失败:', error);
    showStatus('error', '断开连接失败');
  }
};

// 写入数据到打印机
const writeToPrinter = async (data) => {
  if (!isConnected.value || !writeCharacteristic.value) {
    throw new Error('打印机未连接');
  }
  
  try {
    await uni.writeBLECharacteristicValue({
      deviceId: connectedPrinter.value.deviceId,
      serviceId: deviceService.value.uuid,
      characteristicId: writeCharacteristic.value.uuid,
      value: data
    });
  } catch (error) {
    console.error('写入数据失败:', error);
    throw error;
  }
};

// 打印文本
const printText = async (text, options = {}) => {
  try {
    isPrinting.value = true;
    
    // 初始化打印机
    await writeToPrinter(COMMANDS.INIT);
    
    // 设置打印浓度
    await writeToPrinter(COMMANDS.DENSITY(printDensity.value));
    
    // 设置字体大小
    await writeToPrinter(COMMANDS.TEXT_SIZE(parseInt(printFontSize.value)));
    
    // 设置对齐方式
    if (options.align === 'center') {
      await writeToPrinter(COMMANDS.CENTER);
    } else if (options.align === 'right') {
      await writeToPrinter(COMMANDS.RIGHT);
    } else {
      await writeToPrinter(COMMANDS.LEFT);
    }
    
    // 设置粗体
    if (options.bold) {
      await writeToPrinter(COMMANDS.BOLD_ON);
    }
    
    // 打印文本
    await writeToPrinter(text);
    
    // 关闭粗体
    if (options.bold) {
      await writeToPrinter(COMMANDS.BOLD_OFF);
    }
    
    // 换行并切纸
    await writeToPrinter(COMMANDS.LINE_FEED);
    await writeToPrinter(COMMANDS.CUT);
    
    showStatus('success', '打印成功');
  } catch (error) {
    console.error('打印失败:', error);
    showStatus('error', '打印失败');
    throw error;
  } finally {
    isPrinting.value = false;
  }
};

// 测试打印
const testPrint = async () => {
  try {
    await printText('打印测试\n这是一条测试信息\n打印机工作正常\n\n', {
      align: 'center',
      bold: true
    });
  } catch (error) {
    console.error('测试打印失败:', error);
  }
};

// 检查是否是打印机设备
const isPrinterDevice = (device) => {
  const name = (device.name || '').toLowerCase();
  const localName = (device.localName || '').toLowerCase();
  
  // 常见打印机名称关键字
  const keywords = ['print', 'pos', 'thermal', 'receipt', 'ticket', '打印'];
  
  return keywords.some(keyword => 
    name.includes(keyword) || localName.includes(keyword)
  );
};

// 打印浓度变更
const onDensityChange = (e) => {
  printDensity.value = e.detail.value;
};

// 字体大小变更
const onFontSizeChange = (e) => {
  printFontSize.value = e.detail.value;
};

// 生命周期处理
onMounted(() => {
  // 初始化蓝牙
  initBluetooth();
});

onBeforeUnmount(() => {
  // 断开连接
  if (isConnected.value) {
    disconnect();
  }
  
  // 关闭蓝牙
  uni.closeBluetoothAdapter();
});

// 导出组件方法
defineExpose({
  create: async () => {
    try {
      // H5环境不支持蓝牙功能
      // #ifdef H5
      uni.showModal({
        title: '提示',
        content: 'H5环境不支持蓝牙功能，请在APP或小程序中使用',
        showCancel: false
      });
      return false;
      // #endif

      // 初始化蓝牙
      const bleEnabled = await initBluetooth();
      if (!bleEnabled) {
        showStatus('error', '蓝牙初始化失败');
        return false;
      }

      return true;
    } catch (error) {
      console.error('创建打印机实例失败:', error);
      showStatus('error', '创建打印机实例失败');
      return false;
    }
  },
  startSearch,
  stopSearch,
  connectToPrinter,
  disconnect,
  printText,
  setPrintDensity: onDensityChange,
  setFontSize: onFontSizeChange
});
</script>

<style lang="scss">
.xl-printer-container {
  padding: 20rpx;
  
  .printer-status {
    display: flex;
    align-items: center;
    margin-bottom: 20rpx;
    
    .status-badge {
      padding: 6rpx 16rpx;
      border-radius: 30rpx;
      font-size: 24rpx;
      margin-right: 20rpx;
      
      &.status-connected {
        background-color: #e5ffe5;
        color: #07c160;
      }
      
      &.status-disconnected {
        background-color: #f5f5f5;
        color: #666;
      }
    }
    
    .printer-name {
      font-size: 28rpx;
      color: #333;
    }
  }
  
  .printer-controls {
    display: flex;
    gap: 20rpx;
    margin-bottom: 20rpx;
    
    .control-btn {
      flex: 1;
      height: 80rpx;
      line-height: 80rpx;
      font-size: 28rpx;
      border-radius: 8rpx;
      background-color: #007aff;
      color: #fff;
      
      &:disabled {
        opacity: 0.6;
      }
    }
  }
  
  .printer-list {
    background-color: #fff;
    border-radius: 8rpx;
    border: 1px solid #eee;
    margin-bottom: 20rpx;
    
    .list-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 20rpx;
      border-bottom: 1px solid #eee;
      
      text {
        font-size: 28rpx;
        color: #333;
      }
      
      .refresh-btn {
        color: #007aff;
      }
    }
    
    .device-scroll {
      max-height: 400rpx;
      
      .no-device {
        padding: 40rpx;
        text-align: center;
        color: #999;
      }
      
      .device-item {
        display: flex;
        align-items: center;
        padding: 20rpx;
        border-bottom: 1px solid #eee;
        
        &:last-child {
          border-bottom: none;
        }
        
        &.device-connected {
          background-color: rgba(0, 122, 255, 0.05);
        }
        
        .device-icon {
          width: 60rpx;
          height: 60rpx;
          border-radius: 50%;
          background-color: #f5f5f5;
          display: flex;
          align-items: center;
          justify-content: center;
          margin-right: 20rpx;
          
          .icon-printer {
            font-size: 30rpx;
          }
        }
        
        .device-info {
          flex: 1;
          
          .device-name {
            font-size: 28rpx;
            color: #333;
            margin-bottom: 6rpx;
          }
          
          .device-id {
            font-size: 24rpx;
            color: #666;
            margin-bottom: 6rpx;
          }
          
          .device-rssi {
            font-size: 24rpx;
            color: #999;
          }
        }
        
        .device-action {
          font-size: 26rpx;
          
          &.connect-text {
            color: #007aff;
          }
        }
      }
    }
  }
  
  .print-settings {
    background-color: #fff;
    border-radius: 8rpx;
    border: 1px solid #eee;
    padding: 20rpx;
    margin-bottom: 20rpx;
    
    .settings-title {
      font-size: 28rpx;
      font-weight: bold;
      margin-bottom: 20rpx;
    }
    
    .setting-item {
      margin-bottom: 20rpx;
      
      &:last-child {
        margin-bottom: 0;
      }
      
      .setting-label {
        font-size: 26rpx;
        color: #333;
        margin-bottom: 10rpx;
      }
      
      .font-size-group {
        display: flex;
        flex-wrap: wrap;
        
        .font-size-item {
          margin-right: 40rpx;
          display: flex;
          align-items: center;
          
          text {
            font-size: 26rpx;
            margin-left: 6rpx;
          }
        }
      }
    }
  }
  
  .print-content {
    background-color: #fff;
    border-radius: 8rpx;
    border: 1px solid #eee;
    padding: 20rpx;
    margin-bottom: 20rpx;
    
    .content-title {
      font-size: 28rpx;
      font-weight: bold;
      margin-bottom: 20rpx;
    }
    
    .content-textarea {
      width: 100%;
      height: 200rpx;
      border: 1px solid #eee;
      border-radius: 8rpx;
      padding: 20rpx;
      font-size: 28rpx;
      margin-bottom: 20rpx;
    }
    
    .print-btn {
      background-color: #07c160;
      color: #fff;
      font-size: 28rpx;
      border-radius: 8rpx;
      
      &:disabled {
        opacity: 0.6;
      }
    }
  }
  
  .print-status {
    text-align: center;
    margin-top: 20rpx;
    font-size: 28rpx;
    
    .status-success {
      color: #07c160;
    }
    
    .status-error {
      color: #fa5151;
    }
    
    .status-warning {
      color: #ff9800;
    }
    
    .status-info {
      color: #007aff;
    }
  }
}
</style> 